package org.netty.coder.decoder;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import org.apache.log4j.Logger;
import org.netty.utils.PropertyUtils;
import org.netty.utils.serial.SerializeDeserializeWrapper;
import org.netty.utils.serial.SerializeUtils;

import java.util.List;

public class DecoderHandler extends ByteToMessageDecoder {
    private final Logger logger = Logger.getLogger(this.getClass());
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {

        //最小的数据长度：开头标准位1字节 帧头1+帧尾1+数据长度int(4)=6
        int MIN_DATA_LEN = 6;
        if (in.readableBytes()> MIN_DATA_LEN){
            logger.debug("开始解码数据……");
            //标记读操作的指针
            in.markReaderIndex();
            byte header=in.readByte();
            //数据解码协议的开始标志
            byte PROTOCOL_HEADER = PropertyUtils.header;
            if (header== PROTOCOL_HEADER){
                logger.debug("数据开头格式正确");
                //读取字节数据的长度
                    int dataLen=in.readInt();
                    if (dataLen<in.readableBytes()){
                        byte [] data=new byte[dataLen];
                        in.readBytes(data);
                        byte tail=in.readByte();
                        try {
                            //数据解码协议的结束标志
                            byte PROTOCOL_TAIL = PropertyUtils.footer;
                            if (tail== PROTOCOL_TAIL){
                                logger.debug("数据解码成功,开始封装数据……");
                                    Object o = SerializeUtils.deserialize(data, SerializeDeserializeWrapper.class).getData();
                                    out.add(o);
                                //如果out有值，且in仍然可读，将继续调用decode方法再次解码in中的内容，以此解决粘包问题
                            }else {
                                logger.debug(String.format("数据解码协议结束标志位:%1$d [错误!]，期待的结束标志位是：%2$d",tail, PROTOCOL_TAIL));
                            }
                        } catch (Exception e){
                            logger.error(e);
                        }

                    }else{
                        logger.debug(String.format("数据长度不够，数据协议len长度为：%1$d,数据包实际可读内容为：%2$d正在等待处理拆包……",dataLen,in.readableBytes()));
                        in.resetReaderIndex();
                        /*
                         **结束解码，这种情况说明数据没有到齐，在父类ByteToMessageDecoder的callDecode中会对out和in进行判断
                         * 如果in里面还有可读内容即in.isReadable位true,cumulation中的内容会进行保留，，直到下一次数据到来，将两帧的数据合并起来，再解码。
                         * 以此解决拆包问题
                         */
                    }
            }else {
                logger.debug("开头不对，可能不是期待的客服端发送的数，将自动略过这一个字节");
            }
        }else {
            logger.debug("数据长度不符合要求，期待最小长度是："+ MIN_DATA_LEN +" 字节");
        }

    }

}
